﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;

namespace DotNetDAL.Utils
{
    /// <summary>
    /// 通用工具包
    /// </summary>
    public class UtilPackage
    {
        /// <summary>
        /// 换行符
        /// </summary>
        public static string NewLine { get { return System.Environment.NewLine; } }



        #region 检查sql参数值是否包含敏感字符（反注入）

        private const string SqlKeyWord = @" insert into | delete from | count(| drop table | update | truncate | asc( | mid( | char( | xp_cmdshell | exec master | netlocalgroup administrators | net user | or | and |;";
        /// <summary>
        /// 检查sql参数值是否包含敏感字符（反注入）  UtilPackage.CheckSqlParameterValue(sortName,"sortName")
        /// </summary>
        /// <param name="value">变量字段值</param>
        /// <param name="name">变量字段名</param>
        /// <returns></returns>
        public static string CheckSqlParameterValue(string value, string name)
        {
            if (!string.IsNullOrEmpty(value))
            {
                string[] SqlKeyWords = SqlKeyWord.Split(new char[] { '|' });
                bool isHasKeyWord = false;
                string _value = value.ToLower();
                string _keyword = "";
                foreach (string keyword in SqlKeyWords)
                {
                    isHasKeyWord = _value.Contains(keyword);
                    if (isHasKeyWord)
                    {
                        _keyword = keyword;
                        break;
                    }
                }

                if (isHasKeyWord)
                {
                    throw new Exception(name + "值包含SQL敏感字符：\"" + _keyword + "\"。");
                }

            }

            return value;

        }

        #endregion

        #region 对象属性或字段拷贝

        #region 获取拷贝对象的属性或字段值

        /// <summary>
        /// 获取拷贝对象的属性或字段值
        /// </summary>
        /// <param name="paramName">拷贝对象的属性或字段名称</param>
        /// <param name="paramType">拷贝对象的属性或字段类型</param>
        /// <param name="fData">被拷贝对象</param>
        /// <param name="fProperties">被拷贝对象的属性集</param>
        /// <param name="fFieldes">被拷贝对象的字段集</param>
        /// <returns></returns>
        private static object GetCopyValue(string paramName, Type paramType, object fData, PropertyInfo[] fProperties, FieldInfo[] fFieldes)
        {
            if (fData == null) {
                return null;
            }

            // 被拷贝对象的属性集或字段集，有空的，重新获取
            if (fProperties == null || fFieldes == null) {
                Type fType = fData.GetType();
                if (fProperties == null)
                {
                    fProperties = fType.GetProperties();
                }
                if (fFieldes == null)
                {
                    fFieldes = fType.GetFields();
                }
            }

            object _value = null;
            string paramTypeString = paramType.ToString();

            bool isHasProperty = false;
            //获取属性值
            if (fProperties != null)
            {
                PropertyInfo fProperty = fProperties.FirstOrDefault(row => row.Name == paramName);
                if (fProperty != null)
                {
                    isHasProperty = true;

                    object pValue = fProperty.GetValue(fData);
                    try
                    {
                        if (pValue == null)
                        {
                            _value = null;
                        }
                        else if (paramTypeString == "System.String")
                        {
                            _value = Convert.ToString(pValue);
                        }
                        else if (paramTypeString.Contains("System.Nullable"))
                        {
                            _value = Convert.ChangeType(pValue, Nullable.GetUnderlyingType(paramType));
                        }
                        else
                        {
                            _value = Convert.ChangeType(pValue, paramType);
                        }
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("复制属性[" + paramName + "]值时类型转换出错," + ex.Message, ex);
                    }
                }

            }

            //获取字段值
            if (!isHasProperty)
            {
                if (fFieldes != null)
                {
                    FieldInfo fField = fFieldes.FirstOrDefault(row => row.Name == paramName);
                    if (fField != null)
                    {
                        object fValue = fField.GetValue(fData);
                        try
                        {
                            if (fValue == null)
                            {
                                _value = fValue;
                            }
                            else if (paramTypeString == "System.String")
                            {
                                _value = Convert.ToString(fValue);
                            }
                            else if (paramTypeString.Contains("System.Nullable"))
                            {
                                _value = Convert.ChangeType(fValue, Nullable.GetUnderlyingType(paramType));
                            }
                            else
                            {
                                _value = Convert.ChangeType(fValue, paramType);
                            }

                        }
                        catch (Exception ex)
                        {
                            throw new Exception("复制字段[" + paramName + "]值时类型转换出错," + ex.Message, ex);
                        }
                    }
                }

            }

            return _value;
        }

        #endregion

        /// <summary>
        /// 对象属性或字段拷贝
        /// </summary>
        /// <typeparam name="F">被拷贝类</typeparam>
        /// <typeparam name="T">拷贝类</typeparam>
        /// <param name="fData">被拷贝对象</param>
        /// <returns></returns>
        public static T Copy<T>(object fData) where T : class
        {
            if (fData == null) { 
                return default(T);
            }

            Type tType = typeof(T);
            T tData = Activator.CreateInstance<T>();
            bool isFillData = false;


            Type fType = fData.GetType();
            PropertyInfo[] fProperties = fType.GetProperties();
            FieldInfo[] fFieldes = fType.GetFields();

            // 属性值拷贝
            PropertyInfo[] tProperties = tType.GetProperties();
            if (tProperties != null)
            {
                foreach (PropertyInfo tProperty in tProperties)
                {
                    object pVal = GetCopyValue(tProperty.Name, tProperty.PropertyType, fData, fProperties, fFieldes);
                    if (pVal != null)
                    {
                        tProperty.SetValue(tData, pVal);
                        if (!isFillData)
                        {
                            isFillData = true;
                        }
                    }
                }
            }

            // 字段值拷贝
            FieldInfo[] tFieldes = tType.GetFields();
            if (tFieldes != null)
            {
                foreach (FieldInfo tField in tFieldes)
                {
                    object tVal = GetCopyValue(tField.Name, tField.FieldType, fData, fProperties, fFieldes);
                    if (tVal != null)
                    {
                        tField.SetValue(tData, tVal);
                        if (!isFillData)
                        {
                            isFillData = true;
                        }
                    }
                }
            }

            return isFillData ? tData : default(T);
        }


        /// <summary>
        /// 对象属性或字段拷贝
        /// </summary>
        /// <param name="fData"></param>
        /// <returns></returns>
        public static Dictionary<string, object> CopyToDictionary(object fData)
        {
            if (fData == null)
            {
                return default(Dictionary<string, object>);
            }

            bool isFillData = false;
            Dictionary<string, object> tData = new Dictionary<string, object>();

            Type fType = fData.GetType();
            PropertyInfo[] fProperties = fType.GetProperties();
            FieldInfo[] fFieldes = fType.GetFields();

            // 属性值拷贝
            if (fProperties != null)
            {
                foreach (PropertyInfo tProperty in fProperties)
                {
                    tProperty.SetValue(tData, tProperty.GetValue(fData));
                    if (!isFillData)
                    {
                        isFillData = true;
                    }
                }
            }

            // 字段值拷贝
            if (fFieldes != null)
            {
                foreach (FieldInfo tField in fFieldes)
                {
                    tField.SetValue(tData, tField.GetValue(fData));
                    if (!isFillData)
                    {
                        isFillData = true;
                    }
                }
            }

            return isFillData ? tData : default(Dictionary<string, object>);
        }

        #endregion

        #region 对象属性或字段拷贝到目标对象

        /// <summary>
        /// 对象属性或字段拷贝到目标对象
        /// </summary>
        /// <param name="fromData">被拷贝对象</param>
        /// <param name="toData">目标对象</param>
        public static bool CopyTo<T>(object fromData,T toData) where T:class
        {
            if (fromData == null || toData == null)
            {
                return false;
            }
            bool isFillData = false;

            Type fType = fromData.GetType();
            Type tType = toData.GetType();
            
            PropertyInfo[] fProperties = fType.GetProperties();
            FieldInfo[] fFieldes = fType.GetFields();

            // 属性值拷贝
            PropertyInfo[] tProperties = tType.GetProperties();
            if (tProperties != null)
            {
                foreach (PropertyInfo tProperty in tProperties)
                {
                    object pVal = GetCopyValue(tProperty.Name, tProperty.PropertyType, fromData, fProperties, fFieldes);
                    if (pVal != null)
                    {
                        tProperty.SetValue(toData, pVal);
                        if (!isFillData)
                        {
                            isFillData = true;
                        }
                    }
                }
            }

            // 字段值拷贝
            FieldInfo[] tFieldes = tType.GetFields();
            if (tFieldes != null)
            {
                foreach (FieldInfo tField in tFieldes)
                {
                    object tVal = GetCopyValue(tField.Name, tField.FieldType, fromData, fProperties, fFieldes);
                    if (tVal != null)
                    {
                        tField.SetValue(toData, tVal);
                        if (!isFillData)
                        {
                            isFillData = true;
                        }
                    }
                }
            }

            return isFillData;
        }




        #endregion


        #region 列表拷贝

        /// <summary>
        /// 列表拷贝
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fDatas"></param>
        /// <returns></returns>
        public static List<T> CopyList<F,T>(List<F> fDatas) 
            where T : class
            where F : class
        {
            List < T > list= new List<T>();
            if (fDatas == null )
            {
                return list;
            }
            
            var defaultObj = default(T);
            foreach (F row in fDatas)
            {
                T obj = Copy<T>(row);
                if (obj == defaultObj ) {
                    continue;
                }
                list.Add(obj);
            }
            return list;
        }

        #endregion

        #region 判断是否List
        /// <summary>
        /// 判断是否List
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsList(object obj) {
            return obj.GetType().IsGenericType && obj.GetType().GetGenericTypeDefinition() == typeof(List<>);
        }
        #endregion

        #region 合并DataTable

        /// <summary>
        /// 合并DataTable
        /// </summary>
        /// <param name="tables"></param>
        /// <returns></returns>
        public static DataTable MergeDataTable(params DataTable[] tables) {
            DataTable resTable = new DataTable();
            if(tables == null || tables.Length == 0)
            {
                return resTable;
            }
            Dictionary<string, int> columnDIC = new Dictionary<string, int>();
            foreach(DataTable table in tables)
            {
                if(table == null|| table.Rows.Count == 0)
                {
                    continue;
                }
                resTable.Merge(table);

                //foreach(DataColumn dc in table.Columns)
                //{
                //    if (!columnDIC.ContainsKey(dc.ColumnName))
                //    {
                //        resTable.Columns.Add(dc.ColumnName, dc.DataType);
                //    }
                //}

                //foreach (DataRow row in table.Rows)
                //{
                //    DataRow resRow = resTable.NewRow();
                //    foreach (DataColumn dc in table.Columns)
                //    {
                //        if (!columnDIC.ContainsKey(dc.ColumnName))
                //        {
                //            resTable.Columns.Add(dc.ColumnName, dc.DataType);
                //        }
                //    }
                //    resTable.Merge()
                //}





            }

            return resTable;
        }


        #endregion













    }



}
